//// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
//package com.linqingying.gitcode.pullrequest.ui.timeline.item
//
//import com.intellij.collaboration.async.computationState
//import com.intellij.collaboration.async.launchNow
//import com.intellij.collaboration.async.mapDataToModel
//import com.intellij.collaboration.async.transformConsecutiveSuccesses
//import com.intellij.collaboration.ui.codereview.comment.CodeReviewSubmittableTextViewModelBase
//import com.intellij.collaboration.ui.codereview.comment.CodeReviewTextEditingViewModel
//import com.intellij.collaboration.util.ChangesSelection
//import com.intellij.collaboration.util.ComputedResult
//import com.intellij.collaboration.util.SingleCoroutineLauncher
//import com.intellij.openapi.progress.EmptyProgressIndicator
//import com.intellij.openapi.project.Project
//import com.intellij.openapi.util.NlsSafe
//import com.intellij.platform.util.coroutines.childScope
//import com.intellij.util.io.await
//import kotlinx.coroutines.CoroutineName
//import kotlinx.coroutines.CoroutineScope
//import kotlinx.coroutines.cancel
//import kotlinx.coroutines.channels.BufferOverflow
//import kotlinx.coroutines.flow.*
//import com.linqingying.gitcode.api.data.GCActor
//import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestReview
//import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestReviewState
//import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestReviewThread
//import com.linqingying.gitcode.pullrequest.comment.convertToHtml
//import com.linqingying.gitcode.pullrequest.data.GCPRDataContext
//import com.linqingying.gitcode.pullrequest.data.provider.GCPRDataProvider
//import com.linqingying.gitcode.pullrequest.data.provider.GCPRReviewDataProvider
//import com.linqingying.gitcode.pullrequest.data.provider.createThreadsRequestsFlow
//import java.util.*
//
//interface GCPRTimelineReviewViewModel {
//  val author: GCActor
//  val createdAt: Date
//
//  val state: GCPullRequestReviewState
//
//  val bodyHtml: StateFlow<@NlsSafe String>
//
//  val isBusy: StateFlow<Boolean>
//
//  val canEdit: Boolean
//  val editVm: StateFlow<CodeReviewTextEditingViewModel?>
//
//  val threads: StateFlow<ComputedResult<List<GCPRTimelineThreadViewModel>>>
//
//  fun editBody()
//}
//
//class UpdateableGCPRTimelineReviewViewModel internal constructor(
//  private val project: Project,
//  parentCs: CoroutineScope,
//  private val dataContext: GCPRDataContext,
//  private val dataProvider: GCPRDataProvider,
//  initialData: GCPullRequestReview
//) : GCPRTimelineReviewViewModel,
//    GCPRTimelineItem.Review {
//  private val cs = parentCs.childScope(CoroutineName("GitCode Pull Request Timeline Review View Model"))
//  private val reviewData = dataProvider.reviewData
//  private val taskLauncher = SingleCoroutineLauncher(cs)
//
//  private val dataState = MutableStateFlow(initialData)
//
//  private val id = initialData.id
//  override val author: GCActor = initialData.author ?: dataContext.securityService.ghostUser
//  override val createdAt: Date = initialData.createdAt
//  override val state: GCPullRequestReviewState = initialData.state
//
//  override val threads: StateFlow<ComputedResult<List<GCPRTimelineThreadViewModel>>> =
//    reviewData.createThreadsVmsFlow().stateIn(cs, SharingStarted.Eagerly, ComputedResult.loading())
//
//  override val bodyHtml: StateFlow<String> = dataState.map {
//    it.body.convertToHtml(project)
//  }.stateIn(cs, SharingStarted.Eagerly, "")
//
//  override val isBusy: StateFlow<Boolean> = taskLauncher.busy
//
//  override val canEdit: Boolean = initialData.viewerCanUpdate
//
//  private val _editVm = MutableStateFlow<EditViewModel?>(null)
//  override val editVm: StateFlow<CodeReviewTextEditingViewModel?> = _editVm.asStateFlow()
//
//  val showDiffRequests = MutableSharedFlow<ChangesSelection>(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
//
//  override fun editBody() {
//    val currentText = dataState.value.body
//    _editVm.update {
//      (it ?: EditViewModel(currentText)).apply {
//        requestFocus()
//      }
//    }
//  }
//
//  private fun stopEditing() {
//    _editVm.update {
//      it?.dispose()
//      null
//    }
//  }
//
//  fun update(data: GCPullRequestReview) {
//    dataState.value = data
//  }
//
//  private fun GCPRReviewDataProvider.createThreadsVmsFlow() =
//    createThreadsRequestsFlow()
//      .computationState()
//      .transformConsecutiveSuccesses {
//        map { threads -> threads.filter { it.reviewId == id } }.mapDataToModel({ it.id }, { createThread(it) }, { update(it) })
//      }
//
//  private fun CoroutineScope.createThread(data: GCPullRequestReviewThread): UpdateableGCPRTimelineThreadViewModel {
//    val threadVm = UpdateableGCPRTimelineThreadViewModel(project, this, dataContext, dataProvider, data)
//    launchNow {
//      threadVm.showDiffRequests.collect(showDiffRequests)
//    }
//    return threadVm
//  }
//
//  private inner class EditViewModel(initialText: String)
//    : CodeReviewSubmittableTextViewModelBase(project, cs, initialText), CodeReviewTextEditingViewModel {
//    override fun save() {
//      submit { text ->
//        val updated = reviewData.updateReviewBody(EmptyProgressIndicator(), id, text).await()
//        dataState.update {
//          it.copy(body = updated)
//        }
//        stopEditing()
//      }
//    }
//
//    override fun stopEditing() = this@UpdateableGCPRTimelineReviewViewModel.stopEditing()
//
//    fun dispose() = cs.cancel()
//  }
//}
